-- Copyright (c) 2015,2016 Lucky Byte, Inc.
--
-- Summary : 收集平台内可追付的记录
--
-- Author  : 吴小虎 <xiaohu@lucky-byte.com>
-- Since   : 2016.7.13
--
-- History
--  * 2016.7.13 : 创建此文件
--  * 2016.7.25 : 在增加到追付记录时，更新订单的已接受代付标志
--  * 2016.8.24 : 助农代付失败情况下自动追付
--

-- 解析命令行参数
--
local _optargs, _optind = core.getopt(arg, "d:", {
    delay = "d",    -- 代付追付查询延迟（分钟），原交易时间超过此设置值后方收集
})
_optargs.delay = tonumber(_optargs.d)
if not _optargs.delay then
    logger.debug('没有指定查询延迟时间，系统将使用默认值 10 分钟，' ..
        '可以通过参数[--delay=x]设置查询延迟时间.')
    _optargs.delay = 10
end
if _optargs.delay < 10 or _optargs.delay > 240 then
    logger.warn('查询延迟时间[%s]无效，系统将使用默认值 10 分钟.', _optargs.delay)
    _optargs.delay = 10
end
logger.info('代付追付查询延迟时间: %s 分钟.', _optargs.delay)


-- 插入消费代付订单到可追付记录
--
local function _gather_p1_order(p1_order)
    -- 如果是代付失败，则需要确保已经接收到通知报文后才能追付(银联确认失败)
    -- since version 1.2.5
    if p1_order.get('status') == 3 then
        local _table = jdbc.select([[
            select n_pkt from pay_trlist where incoming = false and uuid = ?
        ]], p1_order.get('t40_uuid'));
        if not _table or _table.count == 0 then
            notify.error('未查询到原消费代付交易[%s]的信息，不能追付.',
                p1_order.get('t40_uuid'))
            return
        end
        -- 没有收到通知报文，也没有收到交易查询结果，因此此交易的状态是不明确的，不能追付.
        -- 这笔交易应该等待交易查询之后继续处理(交易查询也是通过任务调度执行)
        if not _table.get_record(0).get('n_pkt') then
            logger.info('代付交易[%s]尚未收到通知报文或交易查询结果，不能追付.',
                p1_order.get('t40_uuid'))
            return
        end
    end

    local _order_uuid = p1_order.get('uuid')

    -- 在加入到可追付记录后，就不再允许终端进行代付
    local _table = jdbc.select([[
        update pay_p1_order set received = true where uuid = ?
            returning received
    ]], _order_uuid)
    if not _table or _table.count == 0 then
        logger.error('更新订单[%s]的已受理标志失败.', _order_uuid)
        return
    end
    if not _table.get_record(0).get('received') then
        logger.error('更新订单[%s]的已受理标志失败.', _order_uuid)
        return
    end

    local _recvr_uuid = uuid()
    jdbc.update([[
        insert into pay_t40_recvr (
            uuid, product, order_uuid, tr_uuid_1, tr_uuid_2, notes
        ) values (
            ?, 'p1', ?, ?, ?, ?
        )
    ]], _recvr_uuid, _order_uuid, p1_order.get('t20_uuid'),
        p1_order.get('t40_uuid'), p1_order.get('notes'))

    logger.info('消费代付订单[%s]创建可追付记录[%s].', _order_uuid, _recvr_uuid)
end


-- 查询状态不正常的消费代付订单, 这些订单将作为可追付记录处理
--
local _table = jdbc.select(string.format([[
    select * from pay_p1_order where
        status in (1, 3) and
        sys_time::date = CURRENT_DATE and
        sys_time::time < CURRENT_TIME - interval '%s minutes' and
        uuid not in (
            select order_uuid from pay_t40_recvr
        )
]], _optargs.delay))

if _table.count == 0 then
    logger.trace('未查询到可追付的消费代付订单...')
else
    logger.debug('查询到[%s]条可追付的消费代付订单...', _table.count)
    for i = 0, _table.count - 1 do
        _gather_p1_order(_table.get_record(i))
    end
end


-- 自动复核待追付记录，免去人工复核
--
local function _check_p2_recvr(recvr_uuid, p2_order)
    -- 只有代付交易确认失败的情况下才允许追付
    local _table = jdbc.select([[
        select json_extract_path_text(i_pkt, 'txnAmt') as amt,
            json_extract_path_text(n_pkt, 'respCode') as resp_code
        from pay_trlist
        where incoming = false and uuid = ?
    ]], p2_order.get('t40_uuid'));
    if not _table or _table.count == 0 then
        notify.error('未查询到原助农代付交易[%s]的信息，自动追付失败.',
            p2_order.get('t40_uuid'))
        return false
    end
    local _record = _table.get_record(0)

    -- 只有 34(查无此交易) 才允许自动追付
    if _record.get('resp_code') ~= '34' then
        notify.warn('只有代付交易响应码为[34]情况下才能自动追付，自动追付失败.')
        return false
    end
    if not _record.get('amt') then
        notify.error('代付报文中未取到交易金额，交易流水为[%s].',
            p2_order.get('t40_uuid'))
        return false
    end
    local _pay_amt = tonumber(_record.get('amt')) / 100

    -- 查询助农代付配置信息
    local _table = jdbc.select([[
        select p2.*, f.overdraw as overdraw
        from pay_p2 as p2
        left join pay_p2_fund as f on f.uuid = p2.p2_fund
        where p2.uuid = ?
    ]], p2_order.get('p2_uuid'))
    if not _table or _table.count == 0 then
        notify.error('未查询到助代付订单[%s]的资金池信息.', p2_order.get('uuid'))
        return false
    end
    local _p2_record = _table.get_record(0)

    -- 更新追付记录为已复核状态
    jdbc.update([[
        update pay_t40_recvr set
            t40_amt = ?, pay_chnl = ?, pay_merid = ?,
            acct_no = ?, acct_name = ?, acct_cred_type = ?, acct_cred_no = ?,
            p2_fund = ?, fee_take_type = ?, fund_lack_proc = ?,
            fund_overdraw = ?,
            inputed = true, input_time = CURRENT_TIMESTAMP,
            checked = true, check_time = CURRENT_TIMESTAMP,
            notes = '系统自动追付，等待调度'
        where uuid = ?
    ]], _pay_amt, _p2_record.get('pay_chnl'), _p2_record.get('pay_merid'),
        _p2_record.get('acct_no'), _p2_record.get('acct_name'),
        _p2_record.get('acct_cred_type'), _p2_record.get('acct_cred_no'),
        _p2_record.get('p2_fund'), _p2_record.get('fee_take_type'),
        _p2_record.get('fund_lack_proc'), _p2_record.get('overdraw'),
        recvr_uuid)
    return true
end


-- 插入助农取款代付订单到可追付记录
--
local function _gather_p2_order(p2_order)
    -- 如果是代付失败，则需要确保已经接收到通知报文后才能追付(银联确认失败)
    -- since version 1.2.5
    if p2_order.get('status') == 3 then
        local _table = jdbc.select([[
            select n_pkt from pay_trlist where incoming = false and uuid = ?
        ]], p2_order.get('t40_uuid'));
        if not _table or _table.count == 0 then
            notify.error('未查询到原助农代付交易[%s]的信息，不能追付.',
                p2_order.get('t40_uuid'))
            return
        end
        -- 没有收到通知报文，也没有收到交易查询结果，因此此交易的状态是不明确的，不能追付.
        -- 这笔交易应该等待交易查询之后继续处理(交易查询也是通过任务调度执行)
        if not _table.get_record(0).get('n_pkt') then
            logger.info('代付交易[%s]尚未收到通知报文或交易查询结果，不能追付.',
                p2_order.get('t40_uuid'))
            return
        end
    end

    local _order_uuid = p2_order.get('uuid')

    -- 在加入到可追付记录后，就不再允许终端进行代付
    local _table = jdbc.select([[
        update pay_p2_order set received = true where uuid = ?
            returning received
    ]], _order_uuid)
    if not _table or _table.count == 0 then
        logger.error('更新订单[%s]的已受理标志失败.', _order_uuid)
        return
    end
    if not _table.get_record(0).get('received') then
        logger.error('更新订单[%s]的已受理标志失败.', _order_uuid)
        return
    end

    -- 插入一条可追付记录，这样至少可以通过人工追付
    local _recvr_uuid = uuid()
    jdbc.update([[
        insert into pay_t40_recvr (
            uuid, product, order_uuid, tr_uuid_1, tr_uuid_2, notes
        ) values (
            ?, 'p2', ?, ?, ?, ?
        )
    ]], _recvr_uuid, _order_uuid, p2_order.get('t60_uuid'),
        p2_order.get('t40_uuid'), p2_order.get('notes'))

    logger.info('助农取款代付订单[%s]创建可追付记录[%s].', _order_uuid, _recvr_uuid)

    -- 如果订单状态为3(代付失败，已确认)，则系统自动将追付记录转换为复核状态，然后等待任务调度
    -- since version 1.2.5
    if p2_order.get('status') == 3 then
        _check_p2_recvr(_recvr_uuid, p2_order)
    end
end


-- 查询状态不正常的助农取款代付订单
-- 这些订单将作为追付记录处理（自动或手动)
--
local _table = jdbc.select(string.format([[
    select * from pay_p2_order where
        status in (1, 3) and
        sys_time::date = CURRENT_DATE and
        sys_time::time < CURRENT_TIME - interval '%s minutes' and
        uuid not in (
            select order_uuid from pay_t40_recvr
        )
]], _optargs.delay))

if _table.count == 0 then
    logger.trace('未查询到可追付的助农取款代付订单...')
else
    logger.debug('查询到[%s]条可追付的助农代付订单...', _table.count)
    for i = 0, _table.count - 1 do
        _gather_p2_order(_table.get_record(i))
    end
end


-- 执行清理，删除隔日尚未追付的记录，这些记录不再有存在的意义，因为系统不允许隔日追付
--
jdbc.update([[
    delete from pay_t40_recvr where done = false and
        ctime::date < CURRENT_DATE
]])
